#include "File/YamlLoader.h"
#include "Functions/Error.h"
#include "Functions/TerminalIO.h"
#include "Riostream.h"
#include "TROOT.h"
#include "TRolke.h"
#include "TSystem.h"
using namespace std;
using namespace BOSS_Afterburner::TerminalIO;

/// @addtogroup Afterburner_scripts
/// @{

/// Based on the [`Rolke` example](https://nbviewer.jupyter.org/url/root.cern.ch/doc/master/notebooks/Rolke.C.nbconvert.ipynb) that comes with ROOT, but adapted with `YamlLoader`.
/// @author   Remco de Boer 雷穆克 (r.e.deboer@students.uu.nl or remco.de.boer@ihep.ac.cn)
/// @date     May 9th, 2019
void Rolke(const char* config_file)
{
  YamlLoader  conf(config_file);
  const auto& model = conf["Model"];
  if(!model) EXCEPTION("YAML file does not contain Model definition");

  Int_t    x     = model["Number of observed events in the experiment"].as<Int_t>();
  Int_t    y     = model["Number of observed events in background region"].as<Int_t>();
  Double_t bm    = model["Estimate of the background"].as<Double_t>();
  Double_t sdb   = model["Standard deviation of the background estimate"].as<Double_t>();
  Double_t em    = model["Estimate of the efficiency"].as<Double_t>();
  Double_t sde   = model["Standard deviation of the efficiency estimate"].as<Double_t>();
  Double_t tau   = model["Ratio between signal and background region"].as<Double_t>();
  Int_t    m     = model["Number of MC events generated"].as<Int_t>();
  Int_t    z     = model["Number of MC events observed"].as<Int_t>();
  Double_t e     = model["True efficiency (considered known)"].as<Double_t>();
  Double_t b     = model["Background expectation value (considered known)"].as<Double_t>();
  Double_t alpha = model["Confidence Level"].as<Double_t>();

  cout << "Number of observed events in the experiment: " << x << endl;
  cout << "Number of observed events in background region: " << y << endl;
  cout << "Estimate of the background: " << bm << endl;
  cout << "Standard deviation of the background estimate: " << sdb << endl;
  cout << "Estimate of the efficiency: " << em << endl;
  cout << "Standard deviation of the efficiency estimate: " << sde << endl;
  cout << "Ratio between signal and background region: " << tau << endl;
  cout << "Number of MC events generated: " << m << endl;
  cout << "Number of MC events observed: " << z << endl;
  cout << "True efficiency (considered known): " << e << endl;
  cout << "Background expectation value (considered known): " << b << endl;
  cout << "Confidence Level: " << alpha << endl;

  TRolke   tr;
  Double_t ul; // Upper limit
  Double_t ll; // Lower limit

  tr.SetCL(alpha);
  tr.SetPoissonBkgBinomEff(x, y, z, tau, m);
  tr.GetLimits(ll, ul);

  cout << endl;
  cout << "The Profile Likelihood interval is:" << endl;
  cout << "[" << ll << "," << ul << "]" << endl;
}
/// @}

int main(int argc, char* argv[])
{
  CheckMainArguments(argc, argv, 1);
  Rolke(argv[1]);
  return 0;
}